package com.itheima.reggie.controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.itheima.reggie.common.R;
import com.itheima.reggie.dto.DishDto;
import com.itheima.reggie.entity.Category;
import com.itheima.reggie.entity.Dish;
import com.itheima.reggie.entity.DishFlavor;
import com.itheima.reggie.service.CategoryService;
import com.itheima.reggie.service.DishFlavorService;
import com.itheima.reggie.service.DishService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.List;

@RestController
@Slf4j
@RequestMapping("/dish")
@Api(tags = "这是菜品展示模块")
public class DishController {
    @Autowired
    private DishService dishService;
    @Autowired
    private CategoryService categoryService;
    @Autowired
    private DishFlavorService dishFlavorService;
    @Autowired
    private RedisTemplate redisTemplate;

    @PostMapping
    @ApiOperation("这个是新增菜品处理器")
    public R<String> update(@RequestBody DishDto dishDto){

        log.info("dishDto:",dishDto);
        //往两个表  添加数据  业务操作  mp完成不了  自己编写业务
        dishService.saveDishAndFlavor(dishDto);

        //每次更新完之后  重新删除redis中的键   重新对数据库查询
        String key = "dish_"+dishDto.getCategoryId();
        redisTemplate.delete(key);//删除指定key
        return R.success("新增菜品成功");

    }
    @GetMapping("/page")
    @ApiOperation("这是菜品查询分页处理器")
    public R<Page> page(int page,int pageSize,String name){
        log.info("菜品分页操作:",page,pageSize,name);
        //创建 分页构造器
        Page<Dish> pageinfo = new Page(page,pageSize);
        // 构造条件构造器
        LambdaQueryWrapper<Dish> wrapper = new LambdaQueryWrapper<>();
        //给wrapper上赋值  模糊条件查询  模糊查询为 like
        //第一个参数 为判断是否为空, 第二个是 实体类中的Name   第三个是前端传来的name;
        wrapper.like(StringUtils.isNotEmpty(name),Dish::getName,name);
        //  如果还想按照 更新日期排序
        wrapper.orderByAsc(Dish::getUpdateTime);
        //  分页查询  执行  service 中的 page方法
        dishService.page(pageinfo,wrapper);
        //此时    没有菜品分类的业务 已经完成了


        //看不到菜品分类名称  原因是 Dish类中 没有 菜品分类名称;
        // Dish 类 要跟数据库对应  所以 在dishDto中添加 菜品分类字段
        Page<DishDto> dishDtoPage = new Page<>();
        //  new的这个对象  啥也没有 ,  需要把 上面的dish对象有的东西复制给它
        // pageInfo  records属性 List<Dish>
        // dishDtoPage  records属性 List<DishDto>
        // 分页信息复制的时候要排除
        BeanUtils.copyProperties(pageinfo,dishDtoPage,"records");
        //dtopage中  所有都搞定了  就差 records
        //List<DishDto> records = new ArrayList<>();
        List<DishDto> records=new ArrayList<>();
        // dish中  有 records  嘎嘎嘎有
        List<Dish> dishRecords = pageinfo.getRecords();
        // 怎么把 recards1 的东西 赋值到  dishdto中

        for (Dish dish : dishRecords) {
            //new出一个 实体类
            DishDto dishDto = new DishDto();
            //再次运用复制  来吧records1的东西 复制给 dishdto
            BeanUtils.copyProperties(dish,dishDto);

            //这里之后  分类名称  是不是应根据 categoryId 进行查询
            Category category = categoryService.getById(dish.getCategoryId());
            //给 这些菜品数据  放到 当前页 list集合中
            dishDto.setCategoryName(category.getName());
            records.add(dishDto);
        }


        dishDtoPage.setRecords(records);
        return R.success(dishDtoPage);

    }
//菜品修改业务之 回显数据
    @GetMapping("/{id}")
    public R<DishDto> getByid(@PathVariable Long id){
        DishDto dishDto = dishService.getByIdWithFlavor(id);
        return R.success(dishDto);
    }



    @PutMapping
    public R<String> update1(@RequestBody DishDto dishDto){
        log.info("[根据id 更新菜品],dishDto:{}",dishDto);
        // dishService有没有方法 可以把 菜品信息和口味信息同时更新的?
        // 木有 因为mp提供的是单表  需要我们"寄几个"来完善
        dishService.updateWithFlavor(dishDto);
        //一样得代码, 删除redis中的缓存 重新 查询
        String key = "dish_"+dishDto.getCategoryId();
        redisTemplate.delete(key);//删除指定key
        return R.success("更新菜品及菜品口味成功");
    }
    /*
    前端查询  根据菜品类型 去查询 菜品信息
    所以有条件查询    返回值为一个List集合  请求参数是id
     */
//    @GetMapping("/list")
//    public R<List<Dish>> getbyid(Dish dish){
//        //创建条件构造器
//        LambdaQueryWrapper<Dish> wrapper = new LambdaQueryWrapper<>();
//        //根据CategoryId字段 去和 前端 传来的 字段 比较 查询
//        wrapper.eq(dish.getCategoryId()!=null,Dish::getCategoryId,dish.getCategoryId());
//        List<Dish> list = dishService.list(wrapper);
//        return R.success(list);
//    }
    ////////////////////这里是 复制老师的代码
    @GetMapping("/list")
    public R<List<DishDto>> list(DishDto dish){




        // 从缓存读取列表数据
        //定义一个用于接收 该分类下菜品 集合的对象
        List<DishDto> redisDtoList = null;
        // 先去 redis 中 找一下 有没有 该分类下的 菜品清单
        //  redis存储 规律是  dish_categoryId
        // dish_categoryId_1
        //从 redis中去读取
        String key = "dish_"+dish.getCategoryId();
        redisDtoList = (List<DishDto>) redisTemplate.opsForValue().get(key);
        log.info("从redis中读取的集合数据:"+redisDtoList);
        if(redisDtoList!=null) {// 缓存中有该分类数据
            log.info("我们的数据是从redis中获取的 没有查询数据库...");
            return R.success(redisDtoList);

        }



        //构建查询条件
        LambdaQueryWrapper<Dish> wrapper = new LambdaQueryWrapper<>();
        //加条件
        wrapper.eq(dish.getCategoryId()!=null,Dish::getCategoryId,dish.getCategoryId());
        // 套餐里面加停售的还是启售的   启售的  status 是1 的
        wrapper.eq(Dish::getStatus,1);
        //你想排就排  --- 有排序字段  没有就按照 更新日期倒序
        wrapper.orderByDesc(Dish::getUpdateTime);
        List<Dish> list = dishService.list(wrapper);

        // 返回 List<DishDto>
        //  把 每一个dish---DishDto  dishDto 根据 菜品id查询到 对应的 口味信息
        //封装到 sishDto的 flavors  属性中
        List<DishDto>  dishDtoList = new ArrayList<>();
        for (Dish dish1 : list) {
            DishDto dishDto = new DishDto();
            BeanUtils.copyProperties(dish1,dishDto);
            // 根据拿到的 dishid 去查询相关的  口味信息
            Long dishId = dish1.getId();
            LambdaQueryWrapper<DishFlavor> wrapper1 = new LambdaQueryWrapper<>();
            wrapper1.eq(DishFlavor::getDishId,dishId);
            List<DishFlavor> flavors = dishFlavorService.list(wrapper1);
            dishDto.setFlavors(flavors);
            Category category = categoryService.getById(dish.getCategoryId());
            dishDto.setCategoryName(category.getName());

            dishDtoList.add(dishDto);
        }
// 如果 redis没数据 就会继续往下执行 也就是执行mp中的sql语句
        // dishDtoList 是 mp查询到的数据  把它放到缓存中
        redisTemplate.opsForValue().set(key,dishDtoList);// 过期时间可设置 可以不用设置
        return R.success(dishDtoList);
    }

}
